home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programmierung
/
Power-Programmierung (Tewi)(1994).iso
/
magazine
/
drdobbs
/
1991
/
02
/
nelson
/
bill.c
next >
Wrap
C/C++ Source or Header
|
1990-06-03
|
6KB
|
200 lines
/*
* Listing 5 -- bill.c
*
* This short demonstration program will use arithmetic data
* compression to encode and then decode a string that only uses
* the letters out of the phrase "BILL GATES". It uses a fixed
* table of probabilities that is hardcoded in. Note that it
* differs from the example in the article in that it adds a single
* new symbol, '\0', which is used to indicate the end of the string.
*
* To build this program:
*
* Turbo C: tcc -w bill.c bitio.c coder.c
* QuickC: qcl /W3 bill.c bitio.c coder.c
* Zortech: ztc bill.c bitio.c coder.c
* *NIX: cc -o bill bill.c bitio.c coder.c
*
*/
#include <stdio.h>
#include <stdlib.h>
#include "coder.h"
#include "bitio.h"
/*
* Declarations for local routines.
*/
void compress( void );
void expand( void );
void convert_int_to_symbol( char c, SYMBOL *s );
char convert_symbol_to_int( unsigned int count, SYMBOL *s );
void error_exit( char *message );
/*
* This is a the probability table for the symbol set used
* in this example. Each symbols has a low and high range,
* and the total count is fixed at 11.
*/
struct {
char c;
unsigned short int low;
unsigned short int high;
} probabilities[]= {{ 'B', 0, 1 },
{ 'I', 1, 2 },
{ 'L', 2, 4 },
{ ' ', 4, 5 },
{ 'G', 5, 6 },
{ 'A', 6, 7 },
{ 'T', 7, 8 },
{ 'E', 8, 9 },
{ 'S', 9, 10 },
{ '\0', 10, 11 }
};
/*
* This example program compresses an input string, sending
* the output to a file. It then expands the output file,
* sending the decoded characters to the screen.
*/
void main()
{
compress();
expand();
}
/*
* This is the compress routine. It shows the basic algorithm for
* the compression programs used in this article. First, an input
* characters is loaded. The modeling routines are called to
* convert the character to a symbol, which has a high, low and
* range. Finally, the arithmetic coder module is called to
* output the symbols to the bit stream.
*/
void compress()
{
int i;
char c;
SYMBOL s;
FILE *compressed_file;
static char *input = "GLIB BATES";
compressed_file=fopen( "test.cmp", "wb" );
if ( compressed_file == NULL )
error_exit( "Could not open output file" );
puts( "Compressing..." );
initialize_output_bitstream();
initialize_arithmetic_encoder();
for ( i=0 ; ; )
{
c = input[ i++ ];
convert_int_to_symbol( c, &s );
encode_symbol( compressed_file, &s );
if ( c == '\0' )
break;
}
flush_arithmetic_encoder( compressed_file );
flush_output_bitstream( compressed_file );
fclose( compressed_file);
}
/*
* This expansion routine demonstrates the basic algorithm used for
* decompression in this article. It first goes to the modeling
* module and gets the scale for the current context. (Note that
* the scale is fixed here, since this is not an adaptive model).
* It then asks the arithmetic decoder to give a high and low
* value for the current input number scaled to match the current
* range. Finally, it asks the modeling unit to convert the
* high and low values to a symbol.
*/
void expand()
{
FILE *compressed_file;
SYMBOL s;
char c;
int count;
compressed_file=fopen( "test.cmp", "rb" );
if ( compressed_file == NULL )
error_exit( "Could not open output file" );
puts( "Decoding..." );
printf( "Incoming characters: " );
initialize_input_bitstream();
initialize_arithmetic_decoder( compressed_file );
for ( ; ; )
{
s.scale = 11;
count = get_current_count( &s );
c = convert_symbol_to_int( count, &s );
if ( c == '\0' )
break;
remove_symbol_from_stream( compressed_file, &s );
putc( c, stdout );
}
putc( '\n', stdout );
}
/*
* This routine is called to convert a character read in from
* the text input stream to a low, high, range SYMBOL. This is
* part of the modeling function. In this case, all that needs
* to be done is to find the character in the probabilities table
* and then retrieve the low and high values for that symbol.
*/
void convert_int_to_symbol( char c, SYMBOL *s )
{
int i;
i=0;
for ( ; ; )
{
if ( c == probabilities[ i ].c )
{
s->low_count = probabilities[ i ].low;
s->high_count = probabilities[ i ].high;
s->scale = 11;
return;
}
if ( probabilities[i].c == '\0' )
error_exit( "Trying to encode a char not in the table" );
i++;
}
}
/*
* This modeling function is called to convert a SYMBOL value
* consisting of a low, high, and range value into a text character
* that can be sent to a file. It does this by finding the symbol
* in the probability table that straddles the current range.
*/
char convert_symbol_to_int( unsigned int count, SYMBOL *s )
{
int i;
i = 0;
for ( ; ; )
{
if ( count >= probabilities[ i ].low &&
count < probabilities[ i ].high )
{
s->low_count = probabilities[ i ].low;
s->high_count = probabilities[ i ].high;
s->scale = 11;
return( probabilities[ i ].c );
}
if ( probabilities[ i ].c == '\0' )
error_exit( "Failure to decode character" );
i++;
}
}
/*
* A generic error routine.
*/
void error_exit( char *message )
{
puts( message );
exit( -1 );
}